package com.jzsec.proxy.jzsecproxy.services;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jzsec.proxy.jzsecproxy.pojo.RequestMsg;
import com.jzsec.proxy.jzsecproxy.utils.SystemUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class LeancloudService {

	@Autowired
	private OkHttpClient okHttpClient;

	private ObjectMapper jsonMapper = new ObjectMapper();

	/**
	 * @param msg json 格式的消息字符串
	 */
	@Async("diyExecutor")
	public void sendMessageByOkHttp(String msg) throws Exception {
		long start = System.currentTimeMillis();
		Map<String, Object> msgMap = jsonMapper.readValue(msg, new TypeReference<Map<String, Object>>() {
		});
		String method = msgMap.get(RequestMsg.METHOD_NAME).toString();
		String url = msgMap.get(RequestMsg.URI).toString();

		Map<String, String> headerMap = null;
		Object headerObj = msgMap.get(RequestMsg.HEADER);
		if (null != headerObj) {
			headerMap = (Map) headerObj;
		}

		Map<String, Object> bodyMap = null;
		Object bodyObj = msgMap.get(RequestMsg.BODY);
		if (null != bodyObj) {
			bodyMap = (Map) bodyObj;
		}
		long httpTimes = sendMessageByOkHttp(method, url, headerMap, bodyMap);
		long end = System.currentTimeMillis();
		long allTimes = (end - start);
		log.info("total 耗时：" + allTimes + ", okHttpClient 耗时：" + httpTimes
				+ ", w/c = " + SystemUtils.getWC(httpTimes, allTimes-httpTimes)
				+ ", threadNum = " + SystemUtils.getThreadNum(httpTimes, allTimes-httpTimes));
	}

	/**
	 * @param methodName post, get, put, delete
	 * @param url
	 * @param headersMap
	 * @param bodyMap
	 * @return
	 * @throws IOException
	 */
	public long sendMessageByOkHttp(String methodName, String url, Map<String, String> headersMap, Map<String, Object> bodyMap)
			throws Exception {
		// header param
		Headers.Builder headerBuilder = new Headers.Builder();
		if (null != headersMap) {
			for (Map.Entry<String, String> entity : headersMap.entrySet()) {
				headerBuilder.set(entity.getKey(), entity.getValue().toString());
			}
		}
		// body param
		RequestBody requestBody = null;
		if (null != bodyMap) {
			String reqBodyStr = jsonMapper.writeValueAsString(bodyMap);
			requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBodyStr);
		}
		// build request
		Request request = new Request.Builder()
				.url(url)
				.headers(headerBuilder.build())
				.method(methodName, requestBody)
				.build();
		long start = System.currentTimeMillis();
		Response response = okHttpClient.newCall(request).execute();
		long end = System.currentTimeMillis();

		Map<String, Object> logMap = new HashMap<String, Object>();
		logMap.put("method", methodName);
		logMap.put("url", url);
		logMap.put("reqHeader", headersMap);
		logMap.put("reqBody", bodyMap);

		String resBodyStr = null;
		if (response.isSuccessful()) {
			resBodyStr = response.body().string();
			logMap.put("resBody", resBodyStr);
			log.info(jsonMapper.writeValueAsString(logMap));
		} else {
			logMap.put("resBody", response.toString());
			log.error(jsonMapper.writeValueAsString(logMap));
			throw new IOException("Unexpected code " + response);
		}
		return (end - start);
	}
}
